package org.mj.im.server.netty.processor.impl;

import cn.hutool.core.bean.BeanUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;

import org.mj.im.common.constants.IMConstants;
import org.mj.im.common.distribute.DistributeCacheService;
import org.mj.im.common.enums.IMCmdType;
import org.mj.im.common.model.IMHeartbeatInfo;
import org.mj.im.common.model.IMSendInfo;
import org.mj.im.server.netty.processor.MessageProcessor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class HeartbeatProcessor implements MessageProcessor<IMHeartbeatInfo> {
    private DistributeCacheService distributedCacheService;

    @Value("${heartbeat.count}")
    private Integer heartbeatCount;

    @Override
    public void process(ChannelHandlerContext ctx, IMHeartbeatInfo data) {
        this.responseWS(ctx);
        AttributeKey<Long> heartbeatAttr = AttributeKey.valueOf(IMConstants.HEARTBEAT_TIMES);
        Long heartbeatTimes = ctx.channel().attr(heartbeatAttr).get();
        ctx.channel().attr(heartbeatAttr).set(++heartbeatTimes);
        if (heartbeatTimes % heartbeatCount == 0) {
            // 心跳10次。用户在线状态续命一次
            AttributeKey<Long> userIdAttr = AttributeKey.valueOf(IMConstants.USER_ID);
            long userId = ctx.channel().attr(userIdAttr).get();
            AttributeKey<Integer> terminalAttr = AttributeKey.valueOf(IMConstants.TERMINAL_TYPE);
            Integer terminal = ctx.channel().attr(terminalAttr).get();
            String redisKey = String.join(IMConstants.REDIS_KEY_SPLIT,IMConstants.IM_USER_SERVER_ID,String.valueOf(userId),String.valueOf(terminal));
            distributedCacheService.expire(redisKey,IMConstants.ONLINE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
        }
    }

    private void responseWS(ChannelHandlerContext ctx) {
        IMSendInfo<?> imSendInfo = new IMSendInfo<>();
        imSendInfo.setCmd(IMCmdType.HEART_BEAT.getCode());
        ctx.channel().writeAndFlush(imSendInfo);
    }

    @Override
    public IMHeartbeatInfo transFrom(Object object) {
        Map<?,?> map = (Map<?,?>) object;
        return BeanUtil.fillBeanWithMap(map,new IMHeartbeatInfo(),false);
    }
}
